package library.xml;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.text.TextUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import library.Library;
import library.logger.Logger;

public class XmlEditor {
    private static final Object LOCK = new Object();
    private static final Context context = Library.getContext();

    @NonNull
    private final SharedPreferences _sp;
    private SharedPreferences.Editor editor;

    protected boolean isAutoCommit() {
        return false;
    }

    private void autoCommit() {
        if (isAutoCommit())
            commit();
    }

    private String getXmlName() {
        return "xml_" + getClass().getSimpleName().toLowerCase().replace("xml", "");
    }

    protected XmlEditor() {
        String name = getXmlName();
        if (TextUtils.isEmpty(name)) {
            _sp = PreferenceManager.getDefaultSharedPreferences(context);
        } else {
            _sp = context.getApplicationContext().getSharedPreferences(name, Context.MODE_PRIVATE);
        }
    }

    private SharedPreferences.Editor getEditor() {
        if (editor == null)
            editor = _sp.edit();
        return editor;
    }

    public synchronized XmlEditor putInt(String Key, int val) {
        getEditor().putInt(Key, val);
        autoCommit();
        return this;
    }

    public int getInt(String Key, int Default) {
        return _sp.getInt(Key, Default);
    }

    public synchronized XmlEditor putLong(String Key, long val) {
        getEditor().putLong(Key, val);
        autoCommit();
        return this;
    }

    public long getLong(String Key, long Default) {
        return _sp.getLong(Key, Default);
    }

    public synchronized XmlEditor putFloat(String Key, float val) {
        getEditor().putFloat(Key, val);
        autoCommit();
        return this;
    }

    public float getFloat(String Key, float Default) {
        return _sp.getFloat(Key, Default);
    }

    public synchronized XmlEditor putString(String Key, String val) {
        getEditor().putString(Key, val);
        autoCommit();
        return this;
    }

    public String getString(String Key, String Default) {
        return _sp.getString(Key, Default);
    }

    public synchronized XmlEditor putBoolean(String Key, boolean val) {
        getEditor().putBoolean(Key, val);
        autoCommit();
        return this;
    }

    public boolean getBoolean(String Key, boolean Default) {
        return _sp.getBoolean(Key, Default);
    }

    public synchronized XmlEditor putSerializable(String Key, Serializable val) {
        ByteArrayOutputStream byteArrayOutputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            byteArrayOutputStream = new ByteArrayOutputStream();
            objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
            objectOutputStream.writeObject(val);
            String serStr = byteArrayOutputStream.toString("ISO-8859-1");
            serStr = java.net.URLEncoder.encode(serStr, "UTF-8");
            objectOutputStream.close();
            byteArrayOutputStream.close();
            putString(Key, serStr);
            autoCommit();
        } catch (Exception e) {
            Logger.debug(e);
        } finally {
            if (byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                }
            }
            if (objectOutputStream != null) {
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                }
            }
        }
        return this;
    }

    public <T> T getSerializable(String Key) {
        String value = getString(Key, null);
        if (value == null)
            return null;
        ByteArrayInputStream byteArrayInputStream = null;
        ObjectInputStream objectInputStream = null;
        try {
            String redStr = java.net.URLDecoder.decode(value, "UTF-8");
            byteArrayInputStream = new ByteArrayInputStream(
                    redStr.getBytes("ISO-8859-1"));
            objectInputStream = new ObjectInputStream(
                    byteArrayInputStream);
            Serializable serializable = (Serializable) objectInputStream.readObject();
            return (T) serializable;
        } catch (Exception e) {
            Logger.debug(e);
        } finally {
            if (byteArrayInputStream != null) {
                try {
                    byteArrayInputStream.close();
                } catch (IOException e) {
                }
            }
            if (objectInputStream != null) {
                try {
                    objectInputStream.close();
                } catch (IOException e) {
                }
            }
        }
        return null;
    }

    public XmlEditor remove(String key) {
        getEditor().remove(key);
        return this;
    }

    public void clean() {
        getEditor().clear();
        commit();
    }

    public boolean commit() {
        synchronized (LOCK) {
            return getEditor().commit();
        }
    }

    public void apply() {
        getEditor().apply();
    }
}
